package com.common.common.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.common.common.option.ColumnOption;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class ExcelIOUtil {

    public static <T> void exportData(List<T> data, List<ColumnOption> columns, HttpServletResponse response, String fileName, String sheet) throws IOException {
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", 
                URLEncoder.encode(fileName == null || fileName.isEmpty() ? "export.xlsx" : fileName, "UTF-8")));
        ExcelWriter writer = ExcelUtil.getWriter(true);
        if (sheet != null && !sheet.isEmpty()) {
            writer.renameSheet(sheet);
        }
        List<String> labels = columns.stream().map(ColumnOption::getLabel).collect(Collectors.toList());
        List<Map<String, Object>> mappedData = mapDataToColumns(data, columns);
        writer.writeHeadRow(labels);
        writer.write(mappedData, true);
        for (int i = 0; i < labels.size(); i++) {
            if (labels.get(i) != null) {
                writer.setColumnWidth(i, labels.get(i).length() * 3);
                writer.setDefaultRowHeight(28);
            }
        }
        CellStyle headCellStyle = writer.getStyleSet().getHeadCellStyle();
        headCellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        //标题字体加粗
        Font font = writer.createFont();
        font.setBold(true);
        headCellStyle.setFont(font);
        writer.flush(response.getOutputStream(), true);
        writer.close();
    }
    
    public static <T> List<T> importData(MultipartFile file, String sheet, List<ColumnOption> columns, Class<T> clazz) throws IOException {
        ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
        if (sheet != null && !sheet.isEmpty()) {
            reader.setSheet(sheet);
        }
        List<Map<String, Object>> data = reader.readAll();
        return data.stream()
                .map(item -> mapColumnsToBean(item, columns, clazz))
                .collect(Collectors.toList());
    }

    private static <T> T mapColumnsToBean(Map<String, Object> data, List<ColumnOption> columns, Class<T> clazz) {
        Map<String, Object> mappedData = new HashMap<>();
        columns.forEach(column -> mappedData.put(column.getProp(), data.get(column.getLabel())));
        return BeanUtil.mapToBean(mappedData, clazz, true);
    }

    private static List<Map<String, Object>> mapDataToColumns(List<?> data, List<ColumnOption> columns) {
        if (data == null || data.isEmpty()) {
            return new ArrayList<>();
        }
        return data.stream()
                .map(item -> mapItemToColumns(item, columns))
                .collect(Collectors.toList());
    }

    private static Map<String, Object> mapItemToColumns(Object item, List<ColumnOption> columns) {
        Map<String, Object> mappedData = BeanUtil.beanToMap(item);
        return columns.stream()
                .collect(Collectors.toMap(ColumnOption::getLabel, column -> mappedData.get(column.getProp())));
    }
}
